#include "sysbreakpad.h"
#ifdef _WIN32
#include <winapi.h>
#include <winsock2.h>

#include "client/windows/handler/exception_handler.h"
#else
#include "client/linux/handler/exception_handler.h"
#include "client/linux/handler/minidump_descriptor.h"
#endif

#include <QProcess>
#include <QFile>
#include <QDir>

//bool onExceptionFilter(void* context, EXCEPTION_POINTERS* exinfo,
//                                 MDRawAssertionInfo* assertion);

#if defined(_WIN32)
//windbg.exe -y . -z dumps\{minidump_id}.dmp -c "kv" -logo dumps\{minidump_id}.txt
bool onMinidumpDumped(const wchar_t* dump_path,
                                   const wchar_t* minidump_id,
                                   void* context,
                                   EXCEPTION_POINTERS* exinfo,
                                   MDRawAssertionInfo* assertion,
                                   bool succeeded)
{
    if(succeeded)
    {
        QString path(QString::fromWCharArray(dump_path));
        path += '\\';
        path += QString::fromWCharArray(minidump_id);
        QString arguments(" -y . -z ");
        arguments += path;
        arguments += ".dmp -c \"kv\" -logo ";
        arguments += path;
        arguments += ".txt";
        QProcess p;
        p.start("windbg.exe" + arguments);

        qlonglong oldSize=0;
        while(true){
            QFile f(path+".txt");
            if(f.exists() && f.size() == oldSize && oldSize)
            {
                break;
            }
            oldSize =f.size();
            p.waitForFinished(100);
        }

    }
    return succeeded;
}
#else
bool onMinidumpDumped(const google_breakpad::MinidumpDescriptor& descriptor,
                                 void* context,
                                 bool succeeded)
{
    return true;
}
#endif

bool InitBreakpad()
{
    QDir dir;
    dir.mkpath("dumps");
#ifdef _WIN32
    google_breakpad::ExceptionHandler *pCrashHandler =
        new google_breakpad::ExceptionHandler(L"dumps",
        nullptr,
        onMinidumpDumped,
        nullptr,
        google_breakpad::ExceptionHandler::HANDLER_ALL,
        MiniDumpNormal,
        static_cast<const wchar_t*>(nullptr),
        nullptr);
#else
    google_breakpad::MinidumpDescriptor descriptor("dumps");
    google_breakpad::ExceptionHandler *pCrashHandler =
        new google_breakpad::ExceptionHandler(descriptor,
        nullptr,
        onMinidumpDumped,
        nullptr,
        true,
        -1);
#endif

    if(pCrashHandler == nullptr) {
        return false;
    }

    return true;
}

SysBreakpad::SysBreakpad()
{

}

void SysBreakpad::f_start(CnsComponentPtr com)
{
    InitBreakpad();
}
